import { FetchAPI, PageParams, Pager, UserRole, UserRoleService } from '../../interface'
import { Db, Filter } from 'mongodb'
import { generateKey } from '../../utils';

export class UserRoleServiceImpl implements UserRoleService {
    public CONN_NAME = 'rbac_role';
    private db: Db
    constructor(db: Db) {
        this.db = db
    }
    getUserRoleByKey: (key: UserRole['key']) => Promise<UserRole | undefined> = async (key) => {
        const conn = this.db.collection<UserRole>(this.CONN_NAME)
        return await conn.findOne({ key }) || undefined
    }
    roleCreate: FetchAPI<UserRole[]> = async (roles) => {
        const keys: string[] = []
        const key_set = new Set(roles.map(p => {
            p.key = p.key || generateKey()
            keys.push(p.key)
            return p.key
        }))
        if (key_set.size !== keys.length) {
            return {
                success: false,
                error: '角色重复',
            }
        }
        const conn = this.db.collection<UserRole>(this.CONN_NAME)
        const exist = await conn.find({ key: { $in: keys } }).toArray()
        if (exist.length) {
            return {
                success: false,
                error: '角色重复',
            }
        }
        await conn.insertMany(roles)
        return {
            success: true,
        }
    }
    roleDelete: FetchAPI<string[]> = async (keys) => {
        const conn = this.db.collection<UserRole>(this.CONN_NAME)
        await conn.deleteMany({ key: { $in: keys } })
        return {
            success: true,
        }
    }
    roleUpdate: FetchAPI<Partial<UserRole> & { key: UserRole['key'] }> = async (role) => {
        const conn = this.db.collection<UserRole>(this.CONN_NAME)
        await conn.updateOne({ key: role.key }, { $set: role })
        return {
            success: true,
        }
    }
    roleList: FetchAPI<PageParams<Partial<UserRole>>, Pager<UserRole>> = async (body) => {
        const { page = 1, pageSize = 10, params = {} } = body;
        const offset = (page - 1) * pageSize
        const conn = this.db.collection<UserRole>(this.CONN_NAME)
        const { key, permissions = [], name, desc } = params
        const filter: Filter<UserRole> = {}
        if (key) {
            filter.key = key
        }
        if (permissions.length) {
            filter.permissions = { $in: permissions }
        }
        if (name) {
            filter.name = { $regex: name, $options: 'i' }
        }
        if (desc) {
            filter.desc = { $regex: desc, $options: 'i' }
        }
        const list = await conn.find(filter).skip(offset).limit(pageSize).toArray()
        return {
            success: true,
            data: {
                list,
                total: await conn.countDocuments(filter),
                page,
                pageSize,
            },
        }
    }
}